﻿/*************************************
Function：增加Html压缩
 Version：1.0
    Date：2013-01-22
  Author：rjdong
   Email：ooxxab@gmail.com
 WebSite：http://emake.info
*************************************
2013-01-22 add [rjdong]:增加Html压缩
**************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Text.RegularExpressions;
using System.Globalization;
using Wind.Compressor.Entity;
using System.IO;

namespace Wind.Compressor.Business
{
    public static class HtmlCompressor
    {

        // Fields
        private static Regex regKeepAll = new Regex(@"(?is)<(pre|script|style|textarea)[^>]*>.*?</\1>");
        private static Regex regStyle = new Regex("(?is)(?<=<style[^>]*>).*?(?=</style>)");

        // Methods
        public static string CssCompress(string cssText)
        {
            return CssCompress(cssText, true);
        }

        public static string CssCompress(string cssText, bool isKeepComment)
        {
            if (isKeepComment)
            {
                cssText = Regex.Replace(cssText, @"(?s)/\*[^!].*?\*/", "");
            }
            else
            {
                cssText = Regex.Replace(cssText, @"(?s)/\*.*?\*/", "");
            }
            cssText = Regex.Replace(cssText, @"\s+", " ");
            cssText = Regex.Replace(cssText, @"([!{}:;>+\(\[,])\s", "$1");
            cssText = Regex.Replace(cssText, @"([^;\}])}", "$1;}");
            cssText = Regex.Replace(cssText, @"([\s:])(0)(?:px|em|%|in|cm|mm|pc|pt|ex)", "$1$2");
            cssText = Regex.Replace(cssText, ":0 0 0 0;|:0 0 0;|:0 0;", ":0;");
            cssText = Regex.Replace(cssText, "(?i)background-position:0;", "background-position:0 0;");
            cssText = Regex.Replace(cssText, @"(?<=[\s:])0+\.(\d+)", ".$1");
            cssText = Regex.Replace(cssText, @"rgb\s*\(([0-9,\s]+)\)", delegate(Match m)
            {
                string[] strArray = m.Groups[1].Value.Split(new char[] { ',' });
                string str = "#";
                foreach (string str2 in strArray)
                {
                    str = str + Convert.ToString(int.Parse(str2, CultureInfo.CurrentCulture), 0x10).PadLeft(2, '0');
                }
                return str;
            });
            cssText = Regex.Replace(cssText, "(?i)(?<=[^\"'=\\s])\\s*#([0-9a-f])\\1([0-9a-f])\\2([0-9a-f])\\3", delegate(Match m)
            {
                return "#" + m.Groups[1].Value + m.Groups[2].Value + m.Groups[3].Value;
            });
            cssText = Regex.Replace(cssText, @"[^\}]+\\{;\}", "");
            cssText = Regex.Replace(cssText, ";{2,}", ";");
            return cssText.Trim();
        }

        public static string HtmlCompress(string htmlText)
        {
            return HtmlCompress(htmlText, true, true, true);
        }

        public static string HtmlCompress(string htmlText, bool removeMulSpace, bool cssCompress, bool cssComment)
        {
            MatchEvaluator evaluator = null;
            string dataKey;
            Dictionary<string, string> keepData = new Dictionary<string, string>();
            int id = 0;
            string prefix = "____UEDSKY.COM_KEEPALL_";
            htmlText = Regex.Replace(htmlText, @"(?is)<!--(?!\[if).*?-->", "");
            htmlText = regKeepAll.Replace(htmlText, delegate(Match m)
            {
                dataKey = prefix + id++ + "____";
                keepData[dataKey] = m.Value;
                return dataKey;
            });
            htmlText = Regex.Replace(htmlText, @"(?<=<[^>]+>)\s+(?=<[^>]+>)", "");
            htmlText = Regex.Replace(htmlText, @"[\r\n]+", "");
            if (removeMulSpace)
            {
                htmlText = Regex.Replace(htmlText, @"\s+", " ");
            }
            htmlText = Regex.Replace(htmlText, prefix + @"\d+____", delegate(Match m)
            {
                return keepData[m.Value];
            });
            if (cssCompress)
            {
                if (evaluator == null)
                {
                    evaluator = delegate(Match m)
                    {
                        return CssCompress(m.Value, cssComment);
                    };
                }
                htmlText = regStyle.Replace(htmlText, evaluator);
            }
            return htmlText.Trim();
        }


        public static string DoCompress(string fileRootPath, string fileMidPath, string fileName, SettingInfo setting, string destPath)
        {
            string result = string.Empty;
            try
            {
                if (!fileRootPath.EndsWith("\\"))
                    fileRootPath += "\\";
                if (!fileMidPath.EndsWith("\\"))
                {
                    if (!string.IsNullOrEmpty(fileMidPath))
                        fileMidPath += "\\";
                }
                if (!destPath.EndsWith("\\"))
                    destPath += "\\";

                string fullFileName = fileRootPath + fileMidPath + fileName;
                
                Encoding encodingHtmlSet = Utils.GetEncoding(setting.HtmlEncodeName);              
                Encoding encodingFile = null;             
                string strContent = Utils.ReadFile(fullFileName, out encodingFile);
                if (encodingHtmlSet == null)
                {
                    if (encodingFile == null)
                        setting.HtmlEncodeName = Encoding.UTF8.EncodingName;
                    else
                        setting.HtmlEncodeName = encodingFile.EncodingName;
                }
                else
                {
                    setting.HtmlEncodeName = encodingHtmlSet.EncodingName;
                }

                string fullname = Path.GetFileName(fileName);

                result = HtmlCompress(strContent, setting.HtmlIsRemoveSpace, setting.HtmlIsCompressCssInStyle, setting.HtmlIsRemoveCssComment);

                Utils.WriteFile(destPath + fileMidPath + fullname, result, Utils.GetEncoding(setting.HtmlEncodeName));
            }
            catch (Exception ex)
            {
                LogHelper.Write("Wind.Compressor.Business.HtmlCompressor.DoCompress error", ex);
            }
            return result;
        }

    }
}


